home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Programmer Disk
/
The Programmer Disk (Microforum).iso
/
xpro
/
extra
/
pro13
/
format.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-01
|
7KB
|
370 lines
/*
format.C
Format function used by v_cprintf () and sprintf ().
Copyright (C) 1993, Geoff Friesen B.Sc.
All rights reserved.
*/
#define INCL_FORMAT
void _prt10 (unsigned num, char *str);
void _prt16 (unsigned num, char *str, int hexcase);
void _prtl10 (unsigned long num, char *str);
void _prtl16 (unsigned long num, char *str, int hexcase);
int pascal format (void (*func) (int), const char *fmt, void *ap)
{
int c; /* current character in format string */
int i; /* loop index */
int sign; /* sign character for positive numeric output */
char fill; /* fill character (' ' or '0') */
int width; /* field width specifier */
char *str; /* running pointer */
int digit1; /* offset to add to first numeric digit */
int length; /* length of string "str" */
int leading; /* # of leading/trailing fill characters */
int hexcase; /* upper/lower-case hex digits flag */
int leftjust; /* 0 = right-justified else left-justified */
int longflag; /* not zero for long numerics */
int count = 0; /* current number of characters output */
char *percent; /* location of most recent percent sign */
char string [20]; /* temporary buffer */
/* ---------------------------------------- */
/* Echo literals and formatted data to func */
/* ---------------------------------------- */
for (;;)
{
/* -------------------------------- */
/* Initialize variables to defaults */
/* -------------------------------- */
sign = ' '; /* positive characters begin with ' ' */
fill = ' '; /* fill character is ' ' */
width = 0; /* width of field */
hexcase = 'L'; /* assume lower-case hex digits */
leftjust = 0; /* numbers are right-justified */
longflag = 0; /* numbers are interpreted as ints */
/* -------------------------------------------- */
/* Echo literals until '%' or end of fmt string */
/* -------------------------------------------- */
while ((c = *fmt++) != '%')
{
if (!c)
return count; /* return if end of format string */
(*func) (c);
count++;
}
/* ---------------------- */
/* Obtain location of '%' */
/* ---------------------- */
percent = (char *) fmt-1;
/* ---------------- */
/* Echo "%%" as '%' */
/* ---------------- */
if (*fmt == '%')
{
(*func) (*fmt++);
count++;
continue;
}
/* ------------------------------------------------------- */
/* Handle format specification: % [flags] [width] [l] type */
/* ------------------------------------------------------- */
/* ----------------- */
/* 1. Handle [flags] */
/* ----------------- */
while ((c = *fmt) == '+' || c == '-')
{
switch (c)
{
case '+': sign = '+';
break;
case '-': leftjust = 1;
}
fmt++;
}
/* -------------- */
/* Handle [width] */
/* -------------- */
fill = (*fmt == '0') ? *fmt++ : ' ';
if (*fmt == '*')
{
width = *((int *) ap)++;
fmt++;
}
else
while ('0' <= *fmt && *fmt <= '9')
width = width*10+*fmt++-'0';
/* ---------- */
/* Handle [l] */
/* ---------- */
if (*fmt == 'l')
{
longflag = 1;
fmt++;
}
/* ----------- */
/* Handle type */
/* ----------- */
str = string;
switch (*fmt++)
{
case 'c' : string [0] = *(int *) ap;
string [1] = '\0';
fill = ' ';
((int *) ap)++;
if (sign == '+')
sign = ' ';
break;
case 's' : str = *(char **) ap;
fill = ' ';
((char **) ap)++;
if (sign == '+')
sign = ' ';
break;
case 'd' :
case 'i' : if (longflag)
{
if (*(long *) ap < 0)
{
sign = '-';
*(long *) ap = -*(long *) ap;
}
}
else
if (*(int *) ap < 0)
{
sign = '-';
*(int *) ap = -*(int *) ap;
}
case 'u' : if (longflag)
{
digit1 = '\0';
while (*(long *) ap < 0)
{
*(long *) ap -= 1000000000L;
++digit1;
}
_prtl10 (*(unsigned long *) ap, str);
((unsigned long *) ap)++;
str [0] += digit1;
}
else
{
_prt10 (*(unsigned *) ap, str);
((unsigned *) ap)++;
}
break;
case 'X' : hexcase = 'U';
case 'x' : if (longflag)
{
_prtl16 (*(unsigned long *) ap, str, hexcase);
((unsigned long *) ap)++;
}
else
{
_prt16 (*(unsigned *) ap, str, hexcase);
((unsigned *) ap)++;
}
if (sign == '+')
sign = ' ';
break;
default : while (*percent)
{
(*func) (*percent++);
count++;
}
return count;
}
for (length = 0; str [length] != '\0'; length++)
;
if (width < 0 || width > 80)
width = 0;
leading = 0;
if (width)
{
if (length > width)
length = width;
leading = width-length;
if (sign == '-' || sign == '+')
--leading;
}
if ((sign == '-' || sign == '+') && fill == '0')
{
(*func) (sign);
count++;
}
if (!leftjust)
for (i = 0; i < leading; i++)
{
(*func) (fill);
count++;
}
if ((sign == '-' || sign == '+') && fill == ' ')
{
(*func) (sign);
count++;
}
for (i = 0; i < length; i++)
{
(*func) (str [i]);
count++;
}
if (leftjust)
for (i = 0; i < leading; i++)
{
(*func) (fill);
count++;
}
}
}
void _prt10 (unsigned num, char *str)
{
int i;
char temp [6];
temp [0] = '\0';
for (i = 1; i <= 5; i++)
{
temp [i] = num % 10 + '0';
num /= 10;
}
for (i = 5; temp [i] == '0'; i--)
;
if (i == 0)
i++;
while (i >= 0)
*str++ = temp [i--];
}
void _prtl10 (unsigned long num, char *str)
{
int i;
char temp [11];
temp [0] = '\0';
for (i = 1; i <= 10; i++)
{
temp [i] = num % 10 + '0';
num /= 10;
}
for (i = 10; temp [i] == '0'; i--)
;
if (i == 0)
i++;
while (i >= 0)
*str++ = temp [i--];
}
void _prt16 (unsigned num, char *str, int hexcase)
{
int i;
char temp [5];
char *hexdigits;
char *hexdigits1 = "0123456789abcdef";
char *hexdigits2 = "0123456789ABCDEF";
temp [0] = '\0';
hexdigits = (hexcase == 'U') ? hexdigits2 : hexdigits1;
for (i = 1; i <= 4; i++)
{
temp [i] = hexdigits [num & 15];
num >>= 4;
}
for (i = 4; temp [i] == '0'; i--)
;
if (!i)
i++;
while (i >= 0)
*str++ = temp [i--];
}
void _prtl16 (unsigned long num, char *str, int hexcase)
{
int i;
char temp [9];
char *hexdigits;
char *hexdigits1 = "0123456789abcdef";
char *hexdigits2 = "0123456789ABCDEF";
temp [0] = '\0';
hexdigits = (hexcase == 'U') ? hexdigits2 : hexdigits1;
for (i = 1; i <= 8; i++)
{
temp [i] = hexdigits [num & 15];
num >>= 4;
}
for (i = 8; temp [i] == '0'; i--)
;
if (!i)
i++;
while (i >= 0)
*str++ = temp [i--];
}